package com.liqiye.paymanager.controller;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.liqiye.paymanager.config.PaymentProperties;
import com.paypal.sdk.PaypalServerSdkClient;
import com.paypal.sdk.controllers.OrdersController;
import com.paypal.sdk.exceptions.ApiException;
import com.paypal.sdk.http.response.ApiResponse;
import com.paypal.sdk.models.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.util.Arrays;
import java.util.Map;
import java.util.UUID;


/**
 * paypal-acdc 预授权
 */
@Slf4j
@RestController
@RequestMapping("/paypal/acdc/card")
public class PaypalACDCPreAuthController {

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private PaypalServerSdkClient client;

    @Autowired
    private PaymentProperties config;

    @Autowired
    private RestTemplate restTemplate;

    private final String baseUrl = "https://api-m.sandbox.paypal.com";
//    private final String baseUrl = "https://api-m.paypal.com";




    /**
     * 预授权
     * 首单：创建订单，并指示保存卡到 vault（ON_SUCCESS）
     * 前端用这个 orderId 调用 CardFields.submit() 完成支付
     */
    @PostMapping("/api/token-payments")
    public ResponseEntity<Object> createTokenPayment(@RequestBody Map<String, Object> body) {

        try {
            String amount = body.getOrDefault("amount","3.33").toString();
            String currency = body.getOrDefault("currency","USD").toString();

            ObjectNode root = objectMapper.createObjectNode();
//            root.put("intent","CAPTURE");
            root.put("intent","AUTHORIZE");

            // 指示在成功支付后把卡存到 vault
            ObjectNode paymentSource = root.putObject("payment_source");
            ObjectNode card = paymentSource.putObject("card");
            ObjectNode attributes = card.putObject("attributes");
            ObjectNode vault = attributes.putObject("vault");
            vault.put("store_in_vault","ON_SUCCESS"); // 或 "ON_APPROVAL"
            // 可选：usage_type 表示 vault 的使用类型（MERCHANT/CUSTOMER）
             vault.put("usage_type","MERCHANT");

            // purchase_units
            ArrayNode pus = root.putArray("purchase_units");
            ObjectNode pu = pus.addObject();
            ObjectNode amt = pu.putObject("amount");
            pu.put("custom_id", "666999");
            amt.put("currency_code", currency);
            amt.put("value", amount);

            String token = this.getAccessToken();
            HttpHeaders headers = new HttpHeaders();
            headers.setBearerAuth(token);
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.add("PayPal-Request-Id", UUID.randomUUID().toString());

            HttpEntity<String> req = new HttpEntity<>(objectMapper.writeValueAsString(root), headers);
            ResponseEntity<String> resp = restTemplate.postForEntity(baseUrl + "/v2/checkout/orders", req, String.class);


            JsonNode orderNode = objectMapper.readTree(resp.getBody());
            String id = orderNode.get("id").asText();
            System.out.println("首单orderId: " + id);


            return ResponseEntity.status(resp.getStatusCode()).body(resp.getBody());



        } catch (HttpClientErrorException e) {
            log.error("createOrderSaveCard error body={}", e.getResponseBodyAsString());
            return ResponseEntity.status(e.getStatusCode()).body(e.getResponseBodyAsString());
        } catch (Exception e) {
            log.error("createOrderSaveCard exception", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
        }

    }


    /**
     * 预授权的捕获支付
     */
    @PostMapping("/api/authorize/{id}")
    public ResponseEntity<Object> authorize(@PathVariable String id) {

        try {


            String token = this.getAccessToken();

            HttpHeaders headers = new HttpHeaders();
            headers.setBearerAuth(token);
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.add("PayPal-Request-Id", UUID.randomUUID().toString());
            HttpEntity<String> req = new HttpEntity<>(headers);
            // 授权订单的支付（冻结首单的资金，获取续费凭证）
            String url = baseUrl + "/v2/checkout/orders/" + id + "/authorize";
            ResponseEntity<String> resp = restTemplate.postForEntity(url, req, String.class);
            System.out.println("===================================");
//            System.out.println(resp.getBody());

            JsonNode orderNode = objectMapper.readTree(resp.getBody());

            JsonNode authorizationIdNode = orderNode.at("/purchase_units/0/payments/authorizations/0/id");
            // 授权id，用来 捕获/取消 付款的
            String authorizationId = authorizationIdNode.isMissingNode() ? null : authorizationIdNode.asText(null);
            System.out.println("authorizationId（授权id，用来 捕获/取消 付款的）: " + authorizationId);

            JsonNode vaultIdNode = orderNode.at("/payment_source/card/attributes/vault/id");
            String vaultId = vaultIdNode.isMissingNode() ? null : vaultIdNode.asText(null);
            System.out.println("vaultId（续费凭证）: " + vaultId);



            boolean preAuth = false;  // 是否满足预授权
            if(preAuth){

                HttpHeaders headers2 = new HttpHeaders();
                headers2.setBearerAuth(token);
                headers2.setContentType(MediaType.APPLICATION_JSON);
                headers2.add("PayPal-Request-Id", UUID.randomUUID().toString());
                HttpEntity<String> req2 = new HttpEntity<>(headers2);
                // 撤销授权（首单不付钱，paypal那边订单变成已作废）
                String url2 = baseUrl + "/v2/payments/authorizations/" + authorizationId + "/void";
                ResponseEntity<String> resp2 = restTemplate.postForEntity(url2, req2, String.class);
                System.out.println("===================================");


            }else{





                HttpHeaders headers2 = new HttpHeaders();
                headers2.setBearerAuth(token);
                headers2.setContentType(MediaType.APPLICATION_JSON);
                headers2.add("PayPal-Request-Id", UUID.randomUUID().toString());
                HttpEntity<String> req2 = new HttpEntity<>(headers2);
                // 捕获授权的支付（首单扣款）
                String url2 = baseUrl + "/v2/payments/authorizations/" + authorizationId + "/capture";
                ResponseEntity<String> resp2 = restTemplate.postForEntity(url2, req2, String.class);
                System.out.println("===================================");
//            System.out.println(resp2.getBody());


                JsonNode captureNode = objectMapper.readTree(resp2.getBody());
                String captureId = captureNode.get("id").asText();
                String captureStatus = captureNode.get("status").asText();
                System.out.println("captureId（首单退款凭证）: " + captureId);
                if (!"COMPLETED".equals(captureStatus)) {
                    System.out.println("首单失败");
                }else{
                    System.out.println("首单成功");
                }






            }






            return ResponseEntity.ok("success");

        } catch (Exception e) {
            log.error("createOrderSaveCard exception", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
        }

    }





    public String getAccessToken() {
        PaymentProperties.PayPal paypal = config.getPaypal();
        String clientId = paypal.getClientId();
        String clientSecret = paypal.getClientSecret();

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.setBasicAuth(clientId, clientSecret);

        MultiValueMap<String,String> body = new LinkedMultiValueMap<>();
        body.add("grant_type","client_credentials");

        HttpEntity<MultiValueMap<String,String>> req = new HttpEntity<>(body, headers);
        ResponseEntity<String> resp = restTemplate.postForEntity(baseUrl + "/v1/oauth2/token", req, String.class);

        try {
            JsonNode node = objectMapper.readTree(resp.getBody());
            return node.get("access_token").asText();
        } catch (Exception e) {
            throw new RuntimeException("getAccessToken error: " + e.getMessage(), e);
        }
    }




    /**
     * 后续扣款（续费）
     */
    @PostMapping("/api/token-payments/charge")
    public ResponseEntity<Object> chargeSavedToken(@RequestBody Map<String, Object> body) {
        try {
            String vaultId = body.get("vaultId").toString();
            String amount = body.getOrDefault("amount","2.22").toString();
            String currency = body.getOrDefault("currency","USD").toString();


            // 可选 previousTransactionReference 如果需要（network token MIT 场景）
//            String prevRef = body.getOrDefault("previousTransactionReference","").toString();

            ObjectNode root = objectMapper.createObjectNode();
            root.put("intent","CAPTURE");

            // payment_source.card.vault_id + stored_credential
            ObjectNode paymentSource = root.putObject("payment_source");
            ObjectNode card = paymentSource.putObject("card");
            card.put("vault_id", vaultId);

            // stored_credential for merchant-initiated subsequent
            ObjectNode stored = card.putObject("stored_credential");
            stored.put("payment_initiator","MERCHANT");
            stored.put("payment_type","RECURRING"); // 或 "ONE_OFF" 按需
            stored.put("usage","SUBSEQUENT");

            ArrayNode pus = root.putArray("purchase_units");
            ObjectNode pu = pus.addObject();
            ObjectNode amt = pu.putObject("amount");
            pu.put("custom_id", "我们的outRequestNo" + UUID.randomUUID());
            amt.put("currency_code", currency);
            amt.put("value", amount);

            String token = this.getAccessToken();
            HttpHeaders headers = new HttpHeaders();
            headers.setBearerAuth(token);
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.add("PayPal-Request-Id", UUID.randomUUID().toString());

            HttpEntity<String> req = new HttpEntity<>(objectMapper.writeValueAsString(root), headers);
            ResponseEntity<String> resp = restTemplate.postForEntity(baseUrl + "/v2/checkout/orders", req, String.class);

            JsonNode createResp = objectMapper.readTree(resp.getBody());
            String orderId = createResp.get("id").asText();
            System.out.println("========================================");
            System.out.println("续费orderId: " + orderId);

            JsonNode captureStatusNode = createResp.at("/purchase_units/0/payments/captures/0/status");
            JsonNode captureIdNode = createResp.at("/purchase_units/0/payments/captures/0/id");
            String captureId = captureIdNode.isMissingNode() ? null : captureIdNode.asText(null);
            String captureStatus = captureStatusNode.isMissingNode() ? null : captureStatusNode.asText();

            System.out.println("captureId（续费退款凭证）: " + captureId);
            if (!"COMPLETED".equals(captureStatus)) {
                // DECLINED / PENDING → 业务上要当失败处理
                System.out.println("续费失败");
            }else{
                System.out.println("续费成功");
            }

            return ResponseEntity.status(resp.getStatusCode()).body(createResp);



        } catch (HttpClientErrorException e) {
            log.error("续费失败 {}", e.getResponseBodyAsString());
            return ResponseEntity.status(e.getStatusCode()).body(e.getResponseBodyAsString());
        } catch (Exception e) {
            log.error("续费失败 ", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
        }

    }




    @PostMapping("/api/token-payments/refund")
    public ResponseEntity<Object> refundPayment(@RequestBody Map<String, Object> body) {
        try {
            String captureId = body.get("captureId").toString(); // 必填
            String amount = body.getOrDefault("amount", "").toString(); // 可选：部分退款
            String currency = body.getOrDefault("currency", "USD").toString();

            ObjectNode root = objectMapper.createObjectNode();
            if (!amount.isEmpty()) {
                ObjectNode amt = root.putObject("amount");
                amt.put("currency_code", currency);
                amt.put("value", amount);
            }

            String token = getAccessToken();
            HttpHeaders headers = new HttpHeaders();
            headers.setBearerAuth(token);
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.add("PayPal-Request-Id", UUID.randomUUID().toString());

            HttpEntity<String> req = new HttpEntity<>(objectMapper.writeValueAsString(root), headers);
            ResponseEntity<String> resp = restTemplate.postForEntity(
                    baseUrl + "/v2/payments/captures/" + captureId + "/refund",
                    req,
                    String.class
            );

            JsonNode jsonNode = objectMapper.readTree(resp.getBody());
            return ResponseEntity.status(resp.getStatusCode()).body(jsonNode);

        } catch (HttpClientErrorException e) {
            log.error("refundPayment error body={}", e.getResponseBodyAsString());
            return ResponseEntity.status(e.getStatusCode()).body(e.getResponseBodyAsString());
        } catch (Exception e) {
            log.error("refundPayment exception", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
        }
    }


    /**
     * 取消订阅
     */
    @PostMapping("/api/token-payments/cancelsubscription")
    public ResponseEntity<Object> cancelSubscription(@RequestBody Map<String, Object> body) {
        try {
            String vaultId = body.get("vaultId").toString();
            String token = this.getAccessToken();
            HttpHeaders headers = new HttpHeaders();
            headers.setBearerAuth(token);
            headers.add("PayPal-Request-Id", UUID.randomUUID().toString());

            HttpEntity<String> req = new HttpEntity<>(headers);

            // 使用 DELETE 方法删除 vault token
            ResponseEntity<String> resp = restTemplate.exchange(
                    baseUrl + "/v3/vault/payment-tokens/" + vaultId,
                    HttpMethod.DELETE,
                    req,
                    String.class
            );

            // 如果删除成功，返回 204 No Content
            if (resp.getStatusCode() == HttpStatus.NO_CONTENT) {
                System.out.println("退订成功");
                return ResponseEntity.noContent().build();
            }
            System.out.println("退订失败");
            return ResponseEntity.status(resp.getStatusCode()).body(resp.getBody());

        } catch (HttpClientErrorException e) {
            log.error("deleteVaultToken error body={}", e.getResponseBodyAsString());

            // 如果凭证不存在或其他错误，返回相应的错误信息
            if (e.getStatusCode() == HttpStatus.NOT_FOUND) {
                return ResponseEntity.status(HttpStatus.NOT_FOUND)
                        .body("Payment token not found");
            }

            return ResponseEntity.status(e.getStatusCode()).body(e.getResponseBodyAsString());
        } catch (Exception e) {
            log.error("deleteVaultToken exception", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
        }

    }



















}
